home *** CD-ROM | disk | FTP | other *** search
- /* Extension dependent execution.
- Copyright (C) 1994, 1995 The Free Software Foundation
-
- Written by: 1995 Jakub Jelinek
- 1994 Miguel de Icaza
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include <config.h>
- #include <stdio.h>
- #include "tty.h"
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include <fcntl.h>
- #include <malloc.h>
- #include <string.h>
- #include <errno.h>
- #include "mad.h"
- #include "user.h"
- #include "main.h"
- #include "fs.h"
- #include "util.h"
- #include "dialog.h"
- #include "global.h"
- #include "ext.h"
- #include "view.h"
- #include "main.h"
- #include "../vfs/vfs.h"
-
- /* "$Id: ext.c,v 1.10 1995/02/21 19:05:45 miguel Exp $" */
- int use_file_to_check_type = 1;
-
- void exec_extension (char *filename, char *data, char *drops, int *move_dir)
- {
- char *file_name;
- FILE *cmd_file;
- int expand_prefix_found = 0;
- int parameter_found = 0;
- char prompt [80];
- int run_view = 0;
- int def_hex_mode = default_hex_mode, changed_hex_mode = 0;
- int def_nroff_flag = default_nroff_flag, changed_nroff_flag = 0;
- int written_nonspace = 0;
- int is_cd = 0;
- char buffer [1024];
- char *p = 0;
- char *localcopy = NULL;
- time_t localmtime = 0;
- struct stat mystat;
- int do_local_copy;
-
- /* Avoid making a local copy if we are doing a cd */
- if (!vfs_file_is_local(filename))
- do_local_copy = 1;
- else
- do_local_copy = 0;
-
- /* Note: this has to be done after the getlocalcopy call,
- * since it uses tmpnam as well
- */
- file_name = strdup (tmpnam (NULL));
-
- if ((cmd_file = fopen (file_name, "w+")) == NULL){
- message (1, " Error ", " Can't create temporary command file \n %s ",
- unix_error_string (errno));
- return;
- }
- prompt [0] = 0;
- for (;*data && *data != '\n'; data++){
- if (parameter_found){
- if (*data == '}'){
- char *parameter;
- parameter_found = 0;
- parameter = input_dialog (" Parameter ", prompt, "");
- if (!parameter){
- /* User canceled */
- fclose (cmd_file);
- unlink (file_name);
- if (localcopy) {
- mc_ungetlocalcopy (filename, localcopy, 0);
- }
- free (file_name);
- return;
- }
- fputs (parameter, cmd_file);
- written_nonspace = 1;
- free (parameter);
- } else {
- int len = strlen (prompt);
-
- if (len < sizeof (prompt) - 1){
- prompt [len] = *data;
- prompt [len+1] = 0;
- }
- }
- } else if (expand_prefix_found){
- expand_prefix_found = 0;
- if (*data == '{')
- parameter_found = 1;
- else {
- int i = check_format_view (data);
- char *v;
-
- if (i){
- data += i - 1;
- run_view = 1;
- } else if ((i = check_format_cd (data)) > 0) {
- is_cd = 1;
- do_local_copy = 0;
- p = buffer;
- data += i - 1;
- } else if ((i = check_format_var (data, &v)) > 0 && v){
- fputs (v, cmd_file);
- free (v);
- data += i;
- } else {
- char *text;
-
- if (*data == 'f' && do_local_copy){
- localcopy = mc_getlocalcopy (filename);
- if (localcopy == NULL) {
- fclose(cmd_file);
- unlink(file_name);
- free(file_name);
- return;
- }
- mc_stat (localcopy, &mystat);
- localmtime = mystat.st_mtime;
- text = strdup (localcopy);
- } else if (*data == 'q') {
- text = strdup (drops);
- } else
- text = expand_format (*data);
- if (!is_cd)
- fputs (text, cmd_file);
- else {
- strcpy (p, text);
- p = strchr (p, 0);
- }
- free (text);
- written_nonspace = 1;
- }
- }
- } else {
- if (*data == '%')
- expand_prefix_found = 1;
- else {
- if (*data != ' ' && *data != '\t')
- written_nonspace = 1;
- if (is_cd)
- *(p++) = *data;
- else
- fputc (*data, cmd_file);
- }
- }
- } /* for */
- fputc ('\n', cmd_file);
- fclose (cmd_file);
- chmod (file_name, S_IRWXU);
- if (run_view){
- altered_hex_mode = 0;
- altered_nroff_flag = 0;
- if (def_hex_mode != default_hex_mode)
- changed_hex_mode = 1;
- if (def_nroff_flag != default_nroff_flag)
- changed_nroff_flag = 1;
-
- /* If we've written whitespace only, then just load filename
- * into view
- */
- if (written_nonspace)
- view (file_name, filename, move_dir);
- else
- view (0, filename, move_dir);
- if (changed_hex_mode && !altered_hex_mode)
- default_hex_mode = def_hex_mode;
- if (changed_nroff_flag && !altered_nroff_flag)
- default_nroff_flag = def_nroff_flag;
- repaint_screen ();
- } else if (is_cd) {
- char *q;
- *p = 0;
- p = buffer;
- while (*p == ' ' || *p == '\t')
- p++;
- q = p;
- while (*q && *q != ' ' && *q != '\t')
- q++;
- *q = 0;
- do_cd (p);
- } else {
- if (vfs_current_is_local ())
- shell_execute (file_name, 1);
- else
- message (1, " Warning ", " Can't execute commands on a Virtual File System directory ");
- }
- unlink (file_name);
- if (localcopy) {
- mc_stat (localcopy, &mystat);
- mc_ungetlocalcopy (filename, localcopy, localmtime != mystat.st_mtime);
- }
- free (file_name);
- }
-
- #ifdef FILE_L
- # define FILE_CMD "file -L "
- #else
- # define FILE_CMD "file "
- #endif
-
- /* The second argument is action, i.e. Open, View, Edit, Drop, or NULL if
- * we want regex_command to return a list of all user defined actions.
- * Third argument is space separated list of dropped files (for actions
- * other then Drop it should be NULL);
- *
- * This function returns:
- *
- * If action != NULL, then it returns "Success" (not allocated) if it ran
- * some command or NULL if not.
- *
- * If action == NULL, it returns NULL if there are no user defined commands
- * or an allocated space separated list of user defined Actions.
- *
- * If action == "Icon", we are doing again something special. We return
- * icon name and we set the variable regex_command_title to Title for
- * that icon.
- */
- static char *data = NULL;
- char *regex_command_title = NULL;
- char *regex_command (char *filename, char *action, char *drops, int *move_dir)
- {
- char *extension_file;
- char *p, *q, *r, c;
- char *buffer;
- int file_len = strlen (filename);
- int found = 0;
- char content_string [2048];
- int content_shift = 0;
- char *to_return = NULL;
- int old_patterns;
- struct stat mystat;
- int asked_file;
-
- #ifdef FILE_STDIN
- int file_supports_stdin = 1;
- #else
- int file_supports_stdin = 0;
- #endif
-
- /* Have we asked file for the file contents? */
- asked_file = 0;
-
- if (data == NULL) {
- int home_error = 0;
-
- buffer = copy_strings (home_dir, PATH_SEP_STR ".mc.ext", 0);
- if (exist_file (buffer))
- extension_file = buffer;
- else
- check_stock_mc_ext:
- extension_file = LIBDIR "mc.ext";
- if ((data = load_file (extension_file)) == NULL) {
- free (buffer);
- return 0;
- }
- if (!strstr (data, "default/")) {
- if (!strstr (data, "regex/") && !strstr (data, "shell/") &&
- !strstr (data, "type/")) {
- free (data);
- data = NULL;
- if (extension_file == buffer) {
- home_error = 1;
- goto check_stock_mc_ext;
- } else {
- message (1, " " LIBDIR "mc.ext file error", "\
- Format of the " LIBDIR "mc.ext file has changed\n\
- with version 3.0. It seems that installation\n\
- failed. Please fetch a fresh new copy from the\n\
- Midnight Commander package or in case you don't\n\
- have any, get it from ftp://ftp.nuclecu.unam.mx.");
- free (buffer);
- return 0;
- }
- }
- }
- if (home_error)
- message (1, " ~/.mc.ext file error ", "\
- Format of the ~/.mc.ext file has changed\n\
- with version 3.0. You may want either to\n\
- copy it from " LIBDIR "mc.ext or use that\n\
- file as an example of how to write it.\n\
- " LIBDIR "mc.ext will be used for this moment.");
- free (buffer);
- }
- mc_stat (filename, &mystat);
-
- regex_command_title = NULL;
- old_patterns = easy_patterns;
- easy_patterns = 0; /* Real regular expressions are needed :) */
- for (p = data; *p; p++) {
- for (q = p; *q == ' ' || *q == '\t'; q++);
- if (*q == '\n' || !*q)
- p = q; /* empty line */
- if (*p == '#') /* comment */
- while (*p && *p != '\n')
- p++;
- if (*p == '\n')
- continue;
- if (!*p)
- break;
- if (p == q) { /* i.e. starts in the first column, should be
- * keyword/descNL
- */
- if (found && action == NULL) /* We have already accumulated all
- * the user actions
- */
- break;
- found = 0;
- q = strchr (p, '\n');
- if (q == NULL)
- q = strchr (p, 0);
- c = *q;
- *q = 0;
- if (!strncmp (p, "regex/", 6)) {
- p += 6;
- /* Do not transform shell patterns, you can use shell/ for
- * that
- */
- if (regexp_match (p, filename, match_normal))
- found = 1;
- } else if (!strncmp (p, "directory/", 10)) {
- if (S_ISDIR (mystat.st_mode) && regexp_match (p, filename, match_normal))
- found = 1;
- } else if (!strncmp (p, "shell/", 6)) {
- p += 6;
- if (*p == '.') {
- if (!strncmp (p, filename + file_len - (q - p),
- q - p))
- found = 1;
- } else {
- if (q - p == file_len && !strncmp (p, filename, q - p))
- found = 1;
- }
- } else if (!strncmp (p, "type/", 5)) {
- int islocal = vfs_file_is_local (filename);
- p += 5;
-
- if (islocal || file_supports_stdin) {
- char *pp;
- int hasread = use_file_to_check_type;
-
- if (asked_file || !use_file_to_check_type)
- goto match_file_output;
-
- hasread = 0;
- if (islocal) {
- char *command =
- copy_strings (FILE_CMD, "'", filename, "'", NULL);
- FILE *f = popen (command, "r");
-
- free (command);
- if (f != NULL) {
- hasread = (fgets (content_string, 2047, f)
- != NULL);
- if (!hasread)
- content_string [0] = 0;
- pclose (f);
- }
- } else {
- #ifdef _OS_NT
- message (1, " NT: Unimplemented file prediction ");
- #else
- int pipehandle, remotehandle;
- pid_t p;
-
- remotehandle = mc_open (filename, O_RDONLY);
- if (remotehandle != -1) {
- /* 8192 is HOWMANY hardcoded value in the file-3.14
- * sources. Tell me if any other file uses larger
- * chunk from beginning
- */
- pipehandle = mc_doublepopen
- (remotehandle, 8192, &p,"file", "file", "-", NULL);
- if (pipehandle != -1) {
- int i;
- while ((i = read (pipehandle, content_string
- + hasread, 2047 - hasread)) > 0)
- hasread += i;
- mc_doublepclose (pipehandle, p);
- content_string [hasread] = 0;
- }
- mc_close (remotehandle);
- }
- #endif /* _OS_NT */
- }
- asked_file = 1;
- match_file_output:
- if (hasread) {
- if ((pp = strchr (content_string, '\n')) != 0)
- *pp = 0;
- if (islocal && !strncmp (content_string,
- filename, file_len)) {
- content_shift = file_len;
- if (content_string [content_shift] == ':')
- for (content_shift++;
- content_string [content_shift] == ' ';
- content_shift++);
- } else if (!islocal
- && !strncmp (content_string,
- "standard input:", 15)) {
- for (content_shift = 15;
- content_string [content_shift] == ' ';
- content_shift++);
- }
- if (content_string &&
- regexp_match (p, content_string +
- content_shift, match_normal)){
- found = 1;
- }
- }
- }
- } else if (!strncmp (p, "default/", 8)) {
- p += 8;
- found = 1;
- }
- *q = c;
- p = q;
- if (!*p)
- break;
- } else { /* List of actions */
- p = q;
- q = strchr (p, '\n');
- if (q == NULL)
- q = strchr (p, 0);
- if (found) {
- r = strchr (p, '=');
- if (r != NULL) {
- c = *r;
- *r = 0;
- if (action == NULL) {
- if (strcmp (p, "Open") &&
- strcmp (p, "View") &&
- strcmp (p, "Edit") &&
- strcmp (p, "Drop") &&
- strcmp (p, "Icon") &&
- strcmp (p, "Title")) {
- /* I.e. this is a name of a user defined action */
- static char *q;
-
- if (to_return == NULL) {
- to_return = xmalloc (512, "Action list");
- q = to_return;
- } else
- *(q++) = ' ';
- strcpy (q, p);
- q = strchr (q, 0);
- }
- *r = c;
- } else if (!strcmp (action, "Icon")) {
- if (!strcmp (p, "Icon") && to_return == NULL) {
- *r = c;
- c = *q;
- *q = 0;
- to_return = strdup (r + 1);
- } else if (!strcmp (p, "Title") && regex_command_title == NULL) {
- *r = c;
- c = *q;
- *q = 0;
- regex_command_title = strdup (r + 1);
- } else {
- *r = c;
- c = *q;
- }
- *q = c;
- if (to_return != NULL && regex_command_title != NULL)
- break;
- } else if (!strcmp (action, p)) {
- *r = c;
- for (p = r + 1; *p == ' ' || *p == '\t'; p++);
- if (p < q) { /* Empty commands just stop searching
- * through, they don't do anything
- */
- exec_extension (filename, r + 1, drops, move_dir);
- to_return = "Success";
- }
- break;
- } else
- *r = c;
- }
- }
- p = q;
- if (!*p)
- break;
- }
- }
- easy_patterns = old_patterns;
- return to_return;
- }
-